package com.heima.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.heima.common.constants.message.FollowBehaviorConstants;
import com.heima.exception.CustomException;
import com.heima.feigns.article.ArticleFeign;
import com.heima.model.article.pojos.ApAuthor;
import com.heima.model.behavior.dtos.FollowBehaviorDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.threadlocal.AppThreadLocalUtils;
import com.heima.model.user.dtos.UserRelationDto;
import com.heima.model.user.pojos.ApUser;
import com.heima.model.user.pojos.ApUserFan;
import com.heima.model.user.pojos.ApUserFollow;
import com.heima.user.mapper.ApUserFanMapper;
import com.heima.user.mapper.ApUserFollowMapper;
import com.heima.user.mapper.ApUserMapper;
import com.heima.user.service.ApUserRelationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
@Service
@Slf4j
public class ApUserRelationServiceImpl implements ApUserRelationService {

    @Autowired
    ArticleFeign articleFeign;

    @Autowired
    ApUserMapper apUserMapper;

    @Autowired
    ApUserFollowMapper apUserFollowMapper;

    @Autowired
    ApUserFanMapper apUserFanMapper;

    @Autowired
    KafkaTemplate<String,String> kafkaTemplate;

    /*@Transactional(rollbackFor = Exception.class)*/  //事物指定异常为Transaction异常
    @Override
    public ResponseResult follow(UserRelationDto dto) {
        //1.检查参数(作者id 操作行为0 或者 1)
        if(dto.getOperation()==null){
           //涉及到事务的方法直接抛异常
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID,"操作行为不能为空");
        }
        if(dto.getAuthorId()==null){
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID,"作者id不能为空");
        }
        //2.远程调用feign接口获取相应的user信息
        ApAuthor author = articleFeign.findById(dto.getAuthorId());
            if(author==null){
                throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST,"作者信息不存在");
            }
        //3.获取本地登录用户
        ApUser loginUser = AppThreadLocalUtils.getUser();
            if(loginUser==null){
                throw new CustomException(AppHttpCodeEnum.NEED_LOGIN);
            }
        //4.行为判断
            //根据作者id获取apuser对象,查验id是否存在
        ApUser followUser = apUserMapper.selectById(dto.getAuthorId());
            if(followUser == null){
                throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST,"作者id不存在");
            }
        //4.1 如果dto中操作行为是 0 则 关注作者
            if(dto.getOperation()==0){
                return followByUserId(loginUser,followUser,dto.getArticleId());
            }
            else{
            //4.2 如果dto中操作行为是 1 则 取关作者
                return followCancelByUserId(loginUser,followUser);
            }
    }

    /**
     * 点击关注
     * @param loginUser
     * @param followUser
     * @return
     */
    private ResponseResult followCancelByUserId(ApUser loginUser, ApUser followUser) {
        // 删除当前用户关注信息
        apUserFollowMapper.delete(Wrappers.<ApUserFollow>lambdaQuery()
                .eq(ApUserFollow::getFollowId, followUser.getId())
                .eq(ApUserFollow::getUserId, loginUser.getId()));
        // 删除被关注的粉丝信息
        apUserFanMapper.delete(Wrappers.<ApUserFan>lambdaQuery()
                .eq(ApUserFan::getFansId, loginUser.getId())
                .eq(ApUserFan::getUserId, followUser.getId()));
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 取消关注
     * @param loginUser
     * @param followUser
     * @param articleId
     * @return
     */
    private ResponseResult followByUserId(ApUser loginUser, ApUser followUser, Long articleId) {
        //1.先查询 是否关注过,select is is
        ApUserFollow apUserFollow = apUserFollowMapper.selectOne(Wrappers.<ApUserFollow>lambdaQuery()
                .eq(ApUserFollow::getUserId, loginUser.getId())
                .eq(ApUserFollow::getFollowId, followUser.getId()));

        if(apUserFollow!=null){
            throw new CustomException(AppHttpCodeEnum.DATA_EXIST,"已经关注过此作者");
        }
        //2.创建关注信息 保存
        apUserFollow = new ApUserFollow();
        apUserFollow.setUserId(loginUser.getId());
        apUserFollow.setFollowId(followUser.getId());
        apUserFollow.setFollowName(followUser.getName());
        apUserFollow.setLevel((short)0);
        apUserFollow.setIsNotice(false);
        apUserFollow.setCreatedTime(new Date());
        apUserFollowMapper.insert(apUserFollow);
        //3.创建粉丝信息 保存
            //先查询
        ApUserFan apUserFan = apUserFanMapper.selectOne(Wrappers.<ApUserFan>lambdaQuery()
                .eq(ApUserFan::getUserId, followUser.getId())
                .eq(ApUserFan::getFansId, loginUser.getId()));

        if(apUserFan == null){
            apUserFan = new ApUserFan();
            apUserFan.setUserId(followUser.getId());
            apUserFan.setFansId(Long.valueOf(loginUser.getId()));
            ApUser apUser = apUserMapper.selectById(loginUser.getId());
            apUserFan.setFansName(apUser.getName());
            apUserFan.setLevel((short)0);
            apUserFan.setCreatedTime(new Date());
            apUserFan.setIsDisplay(false);
            apUserFan.setIsShieldLetter(false);
            apUserFan.setIsShieldComment(false);
            apUserFanMapper.insert(apUserFan);
        } // 当关注成功了
        // 使用kafka将关注行为发送到行为微服务,创建发送消息的dto
        FollowBehaviorDto dto = new FollowBehaviorDto();
        //传递文章id,作者id,用户id
        dto.setArticleId(articleId);
        dto.setFollowId(followUser.getId());
        dto.setUserId(loginUser.getId());
        //kafka进行通知,发送消息封装对象dto..行为微服务接收到消息后将数据保存在对应的行为表中
        kafkaTemplate.send(FollowBehaviorConstants.FOLLOW_BEHAVIOR_TOPIC, JSON.toJSONString(dto));
        log.info("================================已发出kafka消息");
        return ResponseResult.okResult();
    }
}
